﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;

using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO;
using Utility;
using System.Globalization;
using System.Configuration;
using LiquidMeasure.Properties;
using System.Management;
using System.Numerics;
using System.Security.Cryptography;

namespace LiquidMeasure
{
    /// <summary>
    /// Interaction logic for mainwindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        MeasureWindow measureWindow = null;
        SettingWindow settingWindow = new SettingWindow();
        InputBarcode inputBarcodeWindow = null;
        AdjustLayout adjustWindow = null;
        ReportWindow reportWindow = null;
        ObservableCollection<string> windowNames = new ObservableCollection<string>();
        private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
        public MainWindow()
        {
            InitializeComponent();
            
            this.Loaded += new RoutedEventHandler(MainWindow_Loaded);
            this.Closing += new System.ComponentModel.CancelEventHandler(MainWindow_Closing);
        }

        void MainWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            log.Info("windows closing");
            if (measureWindow != null)
                measureWindow.StopCamera();
            gridViewHolder.Children.Clear();
            
        }

        void SetNotRegistCaption()
        {
            this.Title = "未注册软件。";
        }
        void MainWindow_Loaded(object sender, RoutedEventArgs e)
        {
            string sRegCode = ConfigurationManager.AppSettings[stringRes.RegisterCode];
            if (sRegCode.Length < 10)
                SetNotRegistCaption();

            
            BigInteger bigVal = new BigInteger(0);
            for (int i = 0; i < sRegCode.Length; i++)
            {
                bigVal *= 10;
                bigVal += int.Parse(sRegCode[i].ToString());
            }

            bool isPrime = BigIntegerExtensions.IsProbablePrime(bigVal, 10);
            if (!isPrime)
                SetNotRegistCaption();
          
            

            gridViewHolder.Children.Add(settingWindow);
            settingWindow.onFinished += new SettingWindow.Finish(settingWindow_onFinished);
            SetViewTo(SubWindow.Setting);
        }

        //private bool CheckRegisterCode(string pcID)
        //{
        //    string sNewID = "";
        //    for (int i = 0; i < pcID.Length; i += 3)
        //    {
        //        sNewID += pcID[i];
        //    }
        //    Byte[] bytes = System.Text.Encoding.Default.GetBytes(sNewID);
        //    BigInteger bigVal = new BigInteger(0);
        //    for (int i = 0; i < bytes.Length; i++)
        //    {
        //        bigVal *= 100;
        //        bigVal +=  (int)bytes[i];
        //    }

           

        //    for(;;)
        //    {
        //        bool isPrime = BigIntegerExtensions.IsProbablePrime(bigVal, 10);
        //        if (isPrime)
        //            break;
        //        bigVal++;

        //    }
        //    //if (!BigIntegerExtensions.IsProbablePrime(regCode, 10))
        //    return sRegCode == bigVal.ToString();

        //}
       

        public string getCpuInfo()    //读取CPU信息
        {
            ManagementClass mobj = new ManagementClass("Win32_Processor");
            ManagementObjectCollection moc = mobj.GetInstances();
            foreach (ManagementObject mo in moc)
            {
                return mo.Properties["ProcessorId"].Value.ToString();
            }
            return "";
        }
        public string getHddInfo()    //读取硬盘信息
        {
            ManagementClass mobj = new ManagementClass("Win32_PhysicalMedia");
            ManagementObjectCollection moc = mobj.GetInstances();
            foreach (ManagementObject mo in moc)
            {
                return mo.Properties["SerialNumber"].Value.ToString();
            }
            return "";
        }

        static public void EnumVisual(Visual myVisual, Brush color)
        {
            for (int i = 0; i < VisualTreeHelper.GetChildrenCount(myVisual); i++)
            {
                // Retrieve child visual at specified index value.
                Visual childVisual = (Visual)VisualTreeHelper.GetChild(myVisual, i);
                Border theBorder = childVisual as Border;
                if (theBorder != null)
                    theBorder.BorderBrush = color;
                // Enumerate children of the child visual object.
                EnumVisual(childVisual, color);
            }
        }

        void settingWindow_onFinished()
        {
            SetViewTo(SubWindow.ScanBarcode);
        }


        void inputBarcodeWindow_onFinished()
        {
            SetViewTo(SubWindow.Mark);
        }

        void measureWindow_onFinished(bool finished)
        {
            if (!finished)
                SetViewTo(SubWindow.AdjustPostion);
            else
                SetViewTo(SubWindow.Report);
        }

        void adjustWindow_onFinished()
        {
            SetViewTo(SubWindow.ScanBarcode);
        }

        void reportWindow_onFinished()
        {
            this.DialogResult = true;
            this.Close();
        }

        private void SetViewTo(SubWindow subWindow)
        {

            log.InfoFormat("switch view to {0}", subWindow.ToString());
            this.gridViewHolder.Children.Clear();
            switch (subWindow)
            {
                case SubWindow.Setting:
                    this.gridViewHolder.Children.Add(settingWindow);
                    ChangeWindowState(SubWindow.Setting, ProcessState.Doing);
                    break;
                case SubWindow.Mark:
                    //create or show
                    if (measureWindow == null)
                    {
                        measureWindow = new MeasureWindow();
                        measureWindow.onFinished += new MeasureWindow.Finish(measureWindow_onFinished);
                    }
                    else
                    {
                        measureWindow.Visibility = Visibility.Visible;
                    }
                    bool thisBatchLastOne = IsLastBatch();
                    ProcessState scanBarcodeState = thisBatchLastOne ? ProcessState.Finished : ProcessState.Doing;
                    ChangeWindowState(SubWindow.ScanBarcode, scanBarcodeState);
                    ChangeWindowState(SubWindow.Mark, ProcessState.Doing);
                    this.gridViewHolder.Children.Add(measureWindow);
                    break;
                case SubWindow.ScanBarcode:
                    //create or show
                    if (inputBarcodeWindow == null)
                    {
                        inputBarcodeWindow = new InputBarcode();
                        inputBarcodeWindow.onFinished += new InputBarcode.Finish(inputBarcodeWindow_onFinished);
                    }
                    else
                    {
                        inputBarcodeWindow.Visibility = Visibility.Visible;
                        
                    }

                    if (GlobalVals.curBatch == 1) //first time
                    {
                        ChangeWindowState(SubWindow.Setting, ProcessState.Finished);
                        ChangeWindowState(SubWindow.ScanBarcode, ProcessState.Doing);
                    }
                    else
                    {
                        ChangeWindowState(SubWindow.ScanBarcode, ProcessState.Doing);
                        ChangeWindowState(SubWindow.Mark, ProcessState.Doing);
                    }
                    this.gridViewHolder.Children.Add(inputBarcodeWindow);
                    break;
                case SubWindow.AdjustPostion:
                    //create or show
                    if (adjustWindow == null)
                    {
                        adjustWindow = new AdjustLayout();
                        adjustWindow.onFinished += new AdjustLayout.Finish(adjustWindow_onFinished);
                    }
                    else
                    {
                        adjustWindow.Visibility = Visibility.Visible;
                    }
                    
                    ChangeWindowState(SubWindow.AdjustPostion, ProcessState.Doing);
                    this.gridViewHolder.Children.Add(adjustWindow);
                    break;
                case SubWindow.Report:
                    if (reportWindow == null)
                    {
                        reportWindow = new ReportWindow();
                        reportWindow.onFinished += new ReportWindow.Finish(reportWindow_onFinished);
                    }
                    ChangeWindowState(SubWindow.AdjustPostion, ProcessState.Finished);
                    ChangeWindowState(SubWindow.Mark, ProcessState.Finished);
                    ChangeWindowState(SubWindow.Report, ProcessState.Doing);
                    this.gridViewHolder.Children.Add(reportWindow);
                    break;
                default:
                    break;
            }
        }

        private bool IsLastBatch()
        {
            //return GlobalVals.curBatch
            string sSamplePerBatch = ConfigurationManager.AppSettings[stringRes.sampleCountPerGrid];
            int samplesPerBatch = int.Parse(sSamplePerBatch);
            return samplesPerBatch * GlobalVals.curBatch >= GlobalVals.totalSample;
        }
        
        private void ChangeWindowState(SubWindow subWindow, ProcessState processState)
        {
            string windowName = "";
            Dictionary<string, string> dict = new Dictionary<string, string>();
            dict.Add(SubWindow.Setting.ToString(), "1 设置样品");
            dict.Add(SubWindow.ScanBarcode.ToString(), "2 扫描条形码");
            dict.Add(SubWindow.Mark.ToString(), "3 测量液面");
            dict.Add(SubWindow.AdjustPostion.ToString(), "4 放置载架");
            dict.Add(SubWindow.Report.ToString(), "5 报告结果");

            windowName = dict[subWindow.ToString()];
            
            foreach (var item in navigator.Items)
            {
                ShortNameConverter nameConverter = new ShortNameConverter();
                string sCurItem = (string)nameConverter.Convert(item, typeof(string), null, null);


                if (sCurItem == dict[subWindow.ToString()])
                {
                    ListBoxItem container = navigator.ItemContainerGenerator.ContainerFromItem(item) as ListBoxItem;
                    if (processState == ProcessState.Finished)
                    {
                        EnumVisual(container, Brushes.LightBlue);
                        container.IsSelected = true;
                    }
                    if (processState == ProcessState.Doing)
                    {
                        EnumVisual(container, Brushes.OrangeRed);
                    }
                    return;
                }
            }
        }


        public enum ProcessState
        {
            Init = 0,
            Doing = 1,
            Finished = 2

        }
        public enum SubWindow
        {
            Setting, Mark, ScanBarcode, AdjustPostion, Report
        }

        void ShowAbout()
        {
            About aboutWindow = new About();
            aboutWindow.ShowDialog();
        }
            

        public void HelpCmdExecuted(object sender, ExecutedRoutedEventArgs e)
        {
            ShowAbout();
        }

        public void HelpCmdCanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = true;    // Always.
        }
    }
    public static class BigIntegerExtensions
    {
        public static bool IsProbablePrime(this BigInteger source, int certainty)
        {
            if (source == 2 || source == 3)
                return true; if (source < 2 || source % 2 == 0)
                return false;
            BigInteger d = source - 1;
            int s = 0;
            while (d % 2 == 0)
            { d /= 2; s += 1; }
            // There is no built-in method for generating random BigInteger values.   
            // Instead, random BigIntegers are constructed from randomly generated   
            // byte arrays of the same length as the source. 
            RandomNumberGenerator rng = RandomNumberGenerator.Create();
            byte[] bytes = new byte[source.ToByteArray().LongLength];
            BigInteger a;
            for (int i = 0; i < certainty; i++)
            {
                do
                {        // This may raise an exception in Mono 2.10.8 and earlier.       
                    // http://bugzilla.xamarin.com/show_bug.cgi?id=2761        
                    rng.GetBytes(bytes);
                    a = new BigInteger(bytes);
                }
                while (a < 2 || a >= source - 2);
                BigInteger x = BigInteger.ModPow(a, d, source);
                if (x == 1 || x == source - 1)
                    continue;
                for (int r = 1; r < s; r++)
                {
                    x = BigInteger.ModPow(x, 2, source);
                    if (x == 1)
                        return false;
                    if (x == source - 1)
                        break;
                }
                if (x != source - 1)
                    return false;
            } return true;
        }
    }


    [ValueConversion(typeof(string), typeof(string))]
    public class ShortNameConverter : IValueConverter
    {
        public object Convert(object value, Type targetType,
     object parameter, CultureInfo culture)
        {

            string sOrg = value.ToString();
            int pos = sOrg.LastIndexOf('/');
            sOrg = sOrg.Substring(pos+1, sOrg.Length - pos-1);
            sOrg = sOrg.Replace(".png", "");
            return sOrg;
        }



        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return null;
        }
    }


    public static class WindowImageLoader
    {
        public static List<BitmapImage> LoadImages()
        {
            List<BitmapImage> windowIcons = new List<BitmapImage>();
            string sFolder = ".\\resource\\icons";
#if DEBUG
            sFolder = @"D:\work\Projects\LiquidMeasure\LiquidMeasure\bin\Debug" + sFolder;
#endif
            DirectoryInfo robotImageDir = new DirectoryInfo(sFolder);
            foreach (FileInfo robotImageFile in robotImageDir.GetFiles("*.png"))
            {
                Uri uri = new Uri(robotImageFile.FullName);
                windowIcons.Add(new BitmapImage(uri));
            }
            return windowIcons;
        }
    }
}
